//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __ELASTOS_LCDVEE_H__
#define __ELASTOS_LCDVEE_H__

// Port A/B/D Data Register
#define PADR                    ((ioport_t)0x80000000)
#define PBDR                    ((ioport_t)0x80000001)
#define PDDR                    ((ioport_t)0x80000003)

// Port A/B/D Data Direction Register
#define PADDR                   ((ioport_t)0x80000040)
#define PBDDR                   ((ioport_t)0x80000041)
#define PDDDR                   ((ioport_t)0x80000043)

// Port B
#define __VEE_IN               __8BIT(5)
#define __VEE_CLK              __8BIT(6)
#define __VEE_EN               __8BIT(7)

// Port D
#define __VEE_ON_OFF            __8BIT(5)
#define __LCD_EN                __8BIT(2)
#define __LCDEL_EN              __8BIT(1)

INLINE void SetPortBOut()
{
    Outb(PBDDR, Inb(PBDDR) | __VEE_IN | __VEE_CLK | __VEE_EN);
}

INLINE void __Delay(int nLoop)
{
    for (volatile int i = 0; i < nLoop; i++) {
        ;
    }
}

INLINE void VEELowClk()
{
    Outb(PBDR, Inb(PBDR) & (~__VEE_CLK));
}

INLINE void VEEHighClk()
{
    Outb(PBDR, Inb(PBDR) | __VEE_CLK);
}

INLINE void VEELowEn(void)
{
    Outb(PBDR, Inb(PBDR) & (~__VEE_EN));
}

INLINE void VEEHighEn()
{
    Outb(PBDR, Inb(PBDR) | __VEE_EN);
}

INLINE void VEELowIn()
{
    Outb(PBDR, Inb(PBDR) & (~__VEE_IN));
}

INLINE void VEEHighIn()
{
    Outb(PBDR, Inb(PBDR) | __VEE_IN);
}

INLINE void VEERegData(uint8_t u8RegData)
{
    for (int n = 7; n >= 0; n--) {
        if (((u8RegData >> n) & 0x01) == 0) {
            VEELowIn();
        }
        else {
            VEEHighIn();
        }
        __Delay(200);

        VEEHighClk();
        __Delay(3 * 200);

        VEELowClk();
        __Delay(200);
    }

    __Delay(200);
    VEEHighEn();

    __Delay(200);
    VEELowEn();
}

INLINE void SetVBiasOn()
{
    Outb(PDDR, Inb(PDDR) | __VEE_ON_OFF);
}

INLINE void SetLCDELEn(void)
{
    Outb(PDDDR, Inb(PDDDR) & (~__LCDEL_EN));
    __Delay(10);

    Outb(PDDR, Inb(PDDR) | __LCDEL_EN);
    __Delay(10);
}

INLINE void SetLCDEn(void)
{
    Outb(PDDR, Inb(PDDR) | __LCD_EN);
}

INLINE void SetVEE(uint8_t u8RegData)
{
    SetPortBOut();
    __Delay(200);

    VEELowClk();
    VEELowEn();
    __Delay(200);

    VEEHighClk();
    VEEHighEn();
    __Delay(200);

    VEELowEn();
    VEELowClk();
    __Delay(200);

    // Write data
    VEERegData(u8RegData);
    __Delay(200);

    // VEE on
    SetVBiasOn();
}

#endif // __ELASTOS_LCDVEE_H__
